home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 August / macformat-027.iso / mac / Shareware City / Developers / PlayerPRO 4.4.1 Dev.Kit / Import⁄Export / MTM.c < prev    next >
Encoding:
Text File  |  1995-03-14  |  10.5 KB  |  409 lines  |  [TEXT/MPCC]

  1. /********************                        ***********************/
  2. //
  3. //    Player PRO 4.4x -- MTM to MADx & MADx to MTM
  4. //
  5. //    Version 1.0    - 14.3.95 ANR
  6. //
  7. //    To use with CodeWarrior 68K or PPC
  8. //
  9. //    Antoine ROSSET
  10. //    16 Tranchees
  11. //    1206 GENEVA
  12. //    SWITZERLAND
  13. //    
  14. //    FAX:            (+41 22) 346 11 97
  15. //    Compuserve:        100277,164
  16. //    Internet:         rosset@dial.eunet.ch
  17. //
  18. /********************                        ***********************/
  19.  
  20. #include "MTM.h"
  21. #include "MAD.h"
  22. #include "RDriver.h"
  23. #include "PPInOut.h"
  24.  
  25. #if defined(powerc) || defined(__powerc)
  26. enum {
  27.         PlayerPROPlug = kCStackBased
  28.         | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
  29.         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof( OSType)))
  30.         | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof( Ptr*)))
  31.         | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof( MADPartition*)))
  32.         | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof( PPInfoRec*)))
  33.         | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof( short**)))
  34. };
  35.  
  36. ProcInfoType __procinfo = PlayerPROPlug;
  37. #else
  38. #include <A4Stuff.h>
  39. #endif
  40.  
  41. unsigned long Tdecode32( void *msg_buf)
  42. {
  43.   unsigned char *buf = msg_buf;
  44.   
  45.   return( (unsigned long) buf[3] << 24) | ( (unsigned long) buf[2] << 16) | ( (unsigned long) buf[ 1] << 8) | ( (unsigned long) buf[0]);
  46. }
  47.  
  48. short Tdecode16( void *msg_buf)
  49. {
  50.   unsigned char *buf = msg_buf;
  51.   
  52.   return ( (short) buf[1] << 8) | ( (short) buf[0]);
  53. }
  54.  
  55. struct Command* GetCommand( register short PosX, register short    TrackIdX, register    struct MusicPattern*    tempMusicPat)
  56. {
  57.     if( PosX < 0) PosX = 0;
  58.     else if( PosX >= tempMusicPat->header.PatternSize) PosX = tempMusicPat->header.PatternSize -1;
  59.         
  60.     return( & (tempMusicPat->Commands[ (tempMusicPat->header.PatternSize * TrackIdX) + PosX]));
  61. }
  62.  
  63. struct MTMTrack* GetMTMCommand( short position, short whichTracks, Ptr PatPtr)
  64. {
  65.     Ptr                    aPtr;
  66.  
  67.     aPtr =     (    PatPtr +
  68.                 whichTracks * 192L +
  69.                 position * 3L);
  70.  
  71.     return (struct MTMTrack*) aPtr;
  72. }
  73.  
  74. OSErr ConvertMTM2Mad( MTMDef *MTMFile, long MTMSize, MADPartition *theMAD, short *MADpitchTable)
  75. {
  76.     short             i, x, z;
  77.     long             sndSize, OffSetToSample, MPatSize, temp, inOutCount;
  78.     Ptr                MaxPtr;
  79.     OSErr            theErr;
  80.     Ptr                theInstrument[ 64], destPtr;
  81.     
  82.     /**** Variables pour le MAD ****/
  83.     struct Command        *aCmd;
  84.  
  85.     /**** Variables pour le MTM ****/
  86.     
  87.     struct Instru        *instru[ 64];
  88.     struct MTMTrack        *theCom;
  89.     Ptr                    samplePtr, patPtr, positionPtr;
  90.     short                *patTracks; 
  91.     /********************************/
  92.  
  93.     /**** Calcul de divers offsets *****/
  94.  
  95.     MTMFile->tracks = Tdecode16( &MTMFile->tracks);
  96.     MTMFile->comments = Tdecode16( &MTMFile->comments);
  97.     
  98.     MaxPtr         = (Ptr) ( (long)    MTMFile + MTMFile);
  99.     positionPtr    = (Ptr) ( (long)    MTMFile + 66L + MTMFile->NOS*37L);
  100.     patPtr         = (Ptr) ( (long)    MTMFile + 194L + MTMFile->NOS*37L);
  101.     destPtr        = (Ptr) ( (long)    MTMFile + 194L + MTMFile->NOS*37L + MTMFile->tracks*192L);
  102.     patTracks    = (short*) destPtr;
  103.     samplePtr     = (Ptr) ( (long)    MTMFile + 194L + MTMFile->NOS*37L + MTMFile->tracks*192L +
  104.                                     (MTMFile->patNo + 1L)*32L*2L + MTMFile->comments);
  105.     
  106.     /**** Analyse des instruments ****/
  107.     if( MTMFile->NOS > 64) return unknowError;
  108.     
  109.     for( i = 0, OffSetToSample = 0L; i < MTMFile->NOS ; i++)
  110.     {
  111.         theInstrument[ i] = samplePtr + OffSetToSample;
  112.  
  113.         instru[ i] = (struct Instru*) ((long) MTMFile + 66L + i*37L);
  114.  
  115.         instru[ i]->size = Tdecode32( &instru[ i]->size);
  116.         instru[ i]->loopBegin = Tdecode32( &instru[ i]->loopBegin);
  117.         instru[ i]->loopEnd = Tdecode32( &instru[ i]->loopEnd);
  118.  
  119.  
  120.         sndSize = instru[ i]->size;
  121.         if( theInstrument[i] + sndSize > MaxPtr)
  122.         {
  123.             // sndSize = instru[ i]->size = MaxPtr - theInstrument[i];
  124.             return unknowError;
  125.         }
  126.         OffSetToSample += sndSize;
  127.     }
  128.  
  129.  
  130.     /***********************************************/
  131.     /******** Le MTM a été lu et analysé ***********/
  132.     /***** Copie des informations dans le MAD ******/
  133.     /***********************************************/
  134.     
  135.     
  136.     
  137.     /**************************/
  138.     /*** MAD Initialisation ***/
  139.     /**************************/
  140.     
  141.     inOutCount = sizeof( MADSpec);
  142.     theMAD->header = (MADSpec*) NewPtrClear( inOutCount);    
  143.     if( theMAD->header == 0L) return needMoreMemory;
  144.     theMAD->header->MADIdentification = 'MADG';
  145.     
  146.     
  147.     
  148.     /*****************************************/
  149.     /*** Copie des informations MTM -> MAD ***/
  150.     /*****************************************/
  151.     
  152.     for(i=0; i<22; i++)
  153.     {
  154.         theMAD->header->NameSignature[i] = MTMFile->songname[i];
  155.     }
  156.     
  157.     theMAD->header->PatMax                 = MTMFile->patNo + 1;
  158.     theMAD->header->numPointers            = MTMFile->positionNo;
  159.     for(i=0; i<128; i++)
  160.     {
  161.         theMAD->header->oPointers[ i]     = positionPtr[ i];
  162.     }
  163.     theMAD->header->Tracks                 = MTMFile->trackback;
  164.  
  165.     for(i = 0; i < MTMFile->NOS; i++)
  166.     {
  167.         for( x = 0; x < 22; x++) theMAD->header->fid[i].Filename[x] = instru[i]->name[x];
  168.         theMAD->header->fid[i].insSize = instru[i]->size;
  169.         theMAD->header->fid[i].fineTune = instru[i]->fineTune;
  170.         theMAD->header->fid[i].volume = instru[i]->volume;
  171.         theMAD->header->fid[i].freq = 1;
  172.         if( instru[i]->sampleSize == 0) theMAD->header->fid[i].amplitude = 8;
  173.         else theMAD->header->fid[i].amplitude = 16;
  174.         theMAD->header->fid[i].loopStart = instru[i]->loopBegin;
  175.         theMAD->header->fid[i].loopLenght = instru[i]->loopEnd - instru[i]->loopBegin;
  176.         
  177.         if( theMAD->header->fid[ i].insSize > 0)
  178.         {
  179.             theMAD->instrument[ i] = NewPtr( theMAD->header->fid[i].insSize);
  180.             if( theMAD->instrument[ i] != 0L)
  181.             {
  182.                 BlockMove( theInstrument[i], theMAD->instrument[i], theMAD->header->fid[i].insSize);
  183.                 destPtr = theMAD->instrument[i];
  184.                 for( temp = 0; temp < theMAD->header->fid[i].insSize; temp++) *(destPtr + temp) -= 0x80;
  185.             }
  186.             else return needMoreMemory;
  187.         }
  188.         else theMAD->instrument[i] = 0L;
  189.     }
  190.  
  191.     for( i = MTMFile->NOS; i < MAXINSTRU ; i++)
  192.     {
  193.         theMAD->instrument[i] = 0L;
  194.         theMAD->header->fid[i].volume = 64;
  195.         theMAD->header->fid[i].freq = 1;
  196.         theMAD->header->fid[i].amplitude = 8;
  197.     }
  198.     
  199.     
  200.     for(i=0; i<theMAD->header->PatMax; i++)
  201.     {
  202.         
  203.         theMAD->partition[ i] = (struct    MusicPattern*) NewPtrClear( sizeof( struct MusicPattern) + theMAD->header->Tracks * 64L * sizeof( struct Command));
  204.         if( theMAD->partition[ i] == 0L) return needMoreMemory;
  205.  
  206.         theMAD->partition[ i]->header.PatternSize = 64L;
  207.         theMAD->partition[ i]->header.CompressionMode = 'NONE';
  208.  
  209.         for( x = 0; x < 20; x++) theMAD->partition[ i]->header.PatternName[ x] = 0;
  210.  
  211.         theMAD->partition[ i]->header.PatBytes = 0L;
  212.         theMAD->partition[ i]->header.unused2 = 0L;
  213.  
  214.         MaxPtr = (Ptr) theMAD->partition[ i];
  215.         MaxPtr += sizeof( struct MusicPattern) + theMAD->header->Tracks * 64L * sizeof( struct Command);
  216.  
  217.         for( z = 0; z < 32; z++) patTracks[ z] = Tdecode16( &patTracks[ z]);
  218.  
  219.         for(x=0; x<64; x++)
  220.         {
  221.             for(z=0; z<theMAD->header->Tracks; z++)
  222.             {
  223.                 aCmd = GetCommand(  x,  z, theMAD->partition[ i]);
  224.                 if( (Ptr) aCmd + sizeof( struct Command) > MaxPtr) return unknowError;
  225.                 
  226.                 if( patTracks[ z] == 0)
  227.                 {
  228.                     aCmd->InstrumentNo = 0;
  229.                     aCmd->AmigaPeriod = 0;
  230.                     aCmd->EffectCmd = 0;
  231.                     aCmd->EffectArg = 0;
  232.                 }
  233.                 else
  234.                 {
  235.                     theCom         = GetMTMCommand(    x,
  236.                                                     patTracks[ z],
  237.                                                     (Ptr) patPtr);
  238.                     
  239.                     aCmd->InstrumentNo = theCom->instru;
  240.                     aCmd->AmigaPeriod = theCom->pitch;
  241.                     
  242.                     aCmd->EffectCmd = theCom->EffectCmd;
  243.                     aCmd->EffectArg = theCom->EffectArg;
  244.                 }
  245.             }
  246.         }
  247.         
  248.         /*** Avance dans les tracks-patterns suivants ***/
  249.         patTracks += 32;
  250.     }
  251.     
  252.     return noErr;
  253. }
  254.  
  255. OSErr ExtractInfo( PPInfoRec *info, MTMDef *myFile)
  256. {
  257.     long    PatternSize;
  258.     short    i;
  259.     short    maxInstru;
  260.     short    tracksNo;
  261.     
  262.     for( i = 0; i < sizeof( myFile->songname); i++)
  263.     {
  264.         info->internalFileName[ i] = myFile->songname[ i];
  265.     }
  266.     info->internalFileName[ 21] = 0;
  267.     CtoPstr( (Ptr) info->internalFileName);
  268.  
  269.     pStrcpy( info->formatDescription, "\pMTM Plug");
  270.  
  271.     info->totalPatterns        = myFile->patNo;
  272.     info->partitionLength    = myFile->positionNo;
  273.     info->totalTracks        = myFile->tracks;
  274.     info->totalInstruments    = myFile->NOS;
  275.     info->signature            = 'MTM ';
  276.  
  277.     return noErr;
  278. }
  279.  
  280. OSErr TestFile( MTMDef *myFile)
  281. {    
  282.     if(    myFile->Id[ 0] == 'M' &&
  283.         myFile->Id[ 1] == 'T' &&
  284.         myFile->Id[ 2] == 'M') return noErr;
  285.         
  286.     else return fileNotSupportedByThisPlug;
  287. }
  288.  
  289. void pStrcpy(register unsigned char *s1, register unsigned char *s2)
  290. {
  291.     register short len, i;
  292.     
  293.     len = *s2;
  294.     for ( i = 0; i <= len; i++) s1[ i] = s2[ i];
  295. }
  296.  
  297. /*****************/
  298. /* MAIN FUNCTION */
  299. /*****************/
  300.  
  301. OSErr main( OSType order, FSSpec *AlienFileFSSpec, MADPartition *MadFile, PPInfoRec *info, short *MADpitchTable)
  302. {
  303.     OSErr    myErr;
  304.     Ptr        AlienFile;
  305.     short    vRefNum, iFileRefI;
  306.     long    dirID, sndSize;
  307.     
  308. #ifndef powerc
  309.     long    oldA4 = SetCurrentA4();             //this call is necessary for strings in 68k code resources
  310. #endif
  311.  
  312.     HGetVol( 0L, &vRefNum, &dirID);
  313.     HSetVol( 0L, AlienFileFSSpec->vRefNum, AlienFileFSSpec->parID);
  314.  
  315.     myErr = noErr;
  316.  
  317.     switch( order)
  318.     {
  319.         case 'IMPL':
  320.             myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  321.             if( myErr == noErr)
  322.             {
  323.                 GetEOF( iFileRefI, &sndSize);
  324.             
  325.                 // ** TEST MEMOIRE :  Environ 2 fois la taille du fichier**
  326.                 AlienFile = NewPtr( sndSize * 2L);
  327.                 if( AlienFile == 0L) myErr = needMoreMemory;
  328.                 // ** 
  329.                 
  330.                 else
  331.                 {
  332.                     DisposPtr( AlienFile);
  333.                     
  334.                     AlienFile = NewPtr( sndSize);
  335.                     myErr = FSRead( iFileRefI, &sndSize, AlienFile);
  336.                     if( myErr == noErr)
  337.                     {
  338.                         myErr = TestFile( (MTMDef*) AlienFile);
  339.                         if( myErr == noErr)
  340.                         {
  341.                             myErr = ConvertMTM2Mad( (MTMDef*) AlienFile, GetPtrSize( AlienFile), MadFile, MADpitchTable);
  342.                         }
  343.                     }
  344.                     DisposPtr( AlienFile);    AlienFile = 0L;
  345.                 }
  346.                 FSClose( iFileRefI);
  347.             }
  348.         break;
  349.         
  350.         case 'TEST':
  351.             myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  352.             if( myErr == noErr)
  353.             {
  354.                 sndSize = 5000L;    // Read only 5000 first bytes for optimisation
  355.                 
  356.                 AlienFile = NewPtr( sndSize);
  357.                 if( AlienFile == 0L) myErr = needMoreMemory;
  358.                 else
  359.                 {
  360.                     myErr = FSRead( iFileRefI, &sndSize, AlienFile);
  361.                     if( myErr == noErr)
  362.                     {
  363.                         myErr = TestFile( (MTMDef*) AlienFile);
  364.                     }
  365.                     DisposPtr( AlienFile);    AlienFile = 0L;
  366.                 }
  367.                 FSClose( iFileRefI);
  368.             }
  369.         break;
  370.         
  371.         case 'EXPL':
  372.             myErr = orderNotImplemented;
  373.         break;
  374.  
  375.         case 'INFO':
  376.             myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  377.             if( myErr == noErr)
  378.             {
  379.                 GetEOF( iFileRefI, &info->fileSize);
  380.             
  381.                 sndSize = 5000L;    // Read only 5000 first bytes for optimisation
  382.                 
  383.                 AlienFile = NewPtr( sndSize);
  384.                 if( AlienFile == 0L) myErr = needMoreMemory;
  385.                 else
  386.                 {
  387.                     myErr = FSRead( iFileRefI, &sndSize, AlienFile);
  388.                     if( myErr == noErr)
  389.                     {
  390.                         myErr = ExtractInfo( info, (MTMDef*) AlienFile);
  391.                     }
  392.                     DisposPtr( AlienFile);    AlienFile = 0L;
  393.                 }
  394.                 FSClose( iFileRefI);
  395.             }
  396.         break;
  397.         
  398.         default:
  399.             myErr = orderNotImplemented;
  400.         break;
  401.     }
  402.  
  403.     HSetVol( 0L, vRefNum, dirID);
  404.  
  405.     #ifndef powerc
  406.         SetA4( oldA4);
  407.     #endif
  408.     return myErr;
  409. }